#pragma once

#include <string>
#include <vector>
#include <map>

#include <rtc_base/socket_address.h>

#include "base/event_loop.h"
#include "base/network.h"
#include "base/async_udp_socket.h"
#include "ice/ice_def.h"
#include "ice/ice_credentials.h"
#include "ice/candidate.h"
#include "ice/stun.h"

namespace xrtc {

class IceConnection;

// 地址与IceConnection的映射
using AddressMap = std::map<rtc::SocketAddress, IceConnection*>;

class UDPPort : public sigslot::has_slots<> {
public:
    UDPPort(EventLoop* el,
            const std::string& transport_name,
            IceCandidateComponent component,
            IceParameters ice_params);
    ~UDPPort();
    
    // 创建Candidate
    int create_ice_candidate(Network* network, int min_port, int max_port, Candidate& c);

    // 从UDP数据包中提取STUN消息，并调用StunMessage::validate_fingerprint()验证
    bool get_stun_message(const char* data, size_t len, const rtc::SocketAddress& addr,
                          std::unique_ptr<StunMessage>* out_msg, std::string& out_username);

    std::string get_ice_ufrag() const { return m_ice_params.m_ice_ufrag; }
    std::string get_ice_pwd() const { return m_ice_params.m_ice_pwd; }

    const std::string& get_transport_name() const { return m_transport_name; }
    IceCandidateComponent get_component() const { return m_component; }
    const rtc::SocketAddress& get_local_addr() const { return m_local_addr; }

    std::string to_string();

    // 创建IceConnection对象
    IceConnection* create_connection(const Candidate& remote_candidate);
    // 获取IceConnection对象
    IceConnection* get_connection(const rtc::SocketAddress& addr) const;

    // 发送Binding错误响应
    void send_binding_error_response(StunMessage* stun_msg,
        const rtc::SocketAddress& addr,
        int err_code,
        const std::string& reason);

    int send_to(const char* buf, size_t len, const rtc::SocketAddress& addr);

    sigslot::signal4<UDPPort*, const rtc::SocketAddress&, StunMessage*, const std::string&> signal_unknown_address;

private:
    // 处理由AsyncUdpSocket::recv_data()发出的信号，接收Binding请求数据包
    void _on_read_packet(AsyncUdpSocket* socket, char* buf, size_t size,
            const rtc::SocketAddress& addr, int64_t ts);

    // 解析STUN消息的USERNAME属性
    bool _parse_stun_username(StunMessage* stun_msg, std::string& local_ufrag, std::string& remote_ufrag);

private:
    EventLoop* m_el;
    std::string m_transport_name;
    IceCandidateComponent m_component;
    IceParameters m_ice_params;
    int m_socket = -1;
    rtc::SocketAddress m_local_addr;
    std::vector<Candidate> m_candidates;
    std::unique_ptr<AsyncUdpSocket> m_async_socket;
    AddressMap m_connections; // NAT反射地址（客户端NAT映射的反射地址）与IceConnection的映射
};

} // namespace xrtc